#include "modbusscanner.h"

ModbusScanner::ModbusScanner(QObject *parent)
    : QObject{parent}
{
    // 初始化Modbus主站
    modbusMaster = new QModbusRtuSerialMaster(this);
    modbusMaster->setConnectionParameter(QModbusDevice::SerialPortNameParameter, "COM6");
    modbusMaster->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600);
    modbusMaster->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
    modbusMaster->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
    modbusMaster->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);

    // 连接状态信号
    connect(modbusMaster, &QModbusDevice::stateChanged, this, &ModbusScanner::onStateChanged);

}

void ModbusScanner::startScan(int startAddr , int endAddr) {
    if (!modbusMaster->connectDevice()) {
        qDebug() << "Failed to connect RS485 port";
        return;
    }

    // 初始化扫描队列
    for (int addr = startAddr; addr <= endAddr; ++addr) {
        addressQueue.enqueue(addr);
    }

    // 启动首个请求
    sendNextRequest();
}

void ModbusScanner::onStateChanged(QModbusDevice::State state) {
    if (state == QModbusDevice::ConnectedState) {
        qDebug() << "Connected to RS485 port";
    }
}

void ModbusScanner::sendNextRequest() {
    if (addressQueue.isEmpty()) {
        qDebug() << "Scan completed. Active devices:" << activeDevices;
        return;
    }
    qDebug()<<"start scan device";
    int currentAddr = addressQueue.dequeue();
    QModbusDataUnit request(QModbusDataUnit::HoldingRegisters, 0, 1); // 读取寄存器0

    if (auto *reply = modbusMaster->sendReadRequest(request, currentAddr)) {
        if (!reply->isFinished()) {
            connect(reply, &QModbusReply::finished, this, [this, reply, currentAddr]() {
                if (reply->error() == QModbusDevice::NoError) {
                    activeDevices.append(currentAddr);
                    qDebug() << "Device found at address:" << currentAddr;
                }
                reply->deleteLater();
                QTimer::singleShot(50, this, &ModbusScanner::sendNextRequest); // 延时50ms防止总线冲突
            });
        } else {
            reply->deleteLater();
        }
    } else {
        qDebug() << "Request error for address:" << currentAddr;
        QTimer::singleShot(50, this, &ModbusScanner::sendNextRequest);
    }
}

